home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / bipl.zip / PROGS.ZIP / LATEXIDX.ICN < prev    next >
Text File  |  1992-12-30  |  5KB  |  138 lines

  1. ############################################################################
  2. #
  3. #    File:     latexidx.icn
  4. #
  5. #    Subject:  Program to process LaTeX idx file
  6. #
  7. #    Author:   David S. Cargo
  8. #
  9. #    Date:     April 19, 1989
  10. #
  11. ###########################################################################
  12. #
  13. #  Input:
  14. #
  15. #     A latex .idx file containing the \indexentry lines.
  16. #
  17. #  Output:
  18. #
  19. #     \item lines sorted in order by entry value,
  20. #  with page references put into sorted order.
  21. #
  22. # Processing:
  23. #
  24. #     While lines are available from standard input
  25. #         Read a line containing an \indexentry
  26. #         Form a sort key for the indexentry
  27. #         If there is no table entry for it
  28. #         Then create a subtable for it and assign it an initial value
  29. #         If there is a table entry for it,
  30. #         But not an subtable entry for the actual indexentry
  31. #         Then create an initial page number set for it
  32. #         Otherwise add the page number to the corresponding page number set
  33. #    Sort the table of subtables by sort key value
  34. #    For all subtables in the sorted list
  35. #         Sort the subtables by indexentry values
  36. #         For all the indexentries in the resulting list
  37. #             Sort the set of page references
  38. #             Write an \item entry for each indexentry and the page references
  39. #
  40. #  Limitations:
  41. #
  42. #     Length of index handled depends on implementation limits of memory alloc.
  43. #  Page numbers must be integers (no roman numerals).  Sort key formed by
  44. #  mapping to lower case and removing leading articles (a separate function
  45. #  is used to produce the sort key, simplifying customization) -- otherwise
  46. #  sorting is done in ASCII order.
  47. #
  48. ############################################################################
  49.  
  50. procedure main()                       # no parameters, reading from stdin
  51.     local key_table, s, page_num, itemval, key, item_list, one_item
  52.     local page_list, refs
  53.  
  54.     key_table := table()               # for items and tables of page sets
  55.     while s := read() do               # read strings from standard input
  56.         {
  57.         # start with s = "\indexentry{item}{page}"
  58.         # save what's between the opening brace and the closing brace,
  59.         # and reverse it
  60.         s := reverse(s[upto('{',s)+1:-1])
  61.         # giving s = "egap{}meti"
  62.  
  63.         # reversing allows extracting the page number first, thereby allowing
  64.         # ANYTHING to be in the item field
  65.  
  66.         # grab the "egap", reverse it, convert to integer, convert to set
  67.         # in case of conversion failure, use 0 as the default page number
  68.         page_num := set([integer(reverse(s[1:upto('{',s)])) | 0])
  69.  
  70.         # the reversed item starts after the first closing brace
  71.         # grab the "meti", reverse it
  72.         itemval := reverse(s[upto('}', s)+1:0])
  73.  
  74.         # allow the sort key to be different from the item
  75.         # reform may be customized to produce different equivalence classes
  76.         key := reform(itemval)
  77.  
  78.         # if the assigned value for the key is null
  79.         if /key_table[key]
  80.         then
  81.             {
  82.             # create a subtable for the key and give it its initial value
  83.             key_table[key] := table()
  84.             key_table[key][itemval] := page_num
  85.             }
  86.  
  87.         # else if the assigned value for the itemval is null
  88.         # (e. g., when the second itemval associated with a key is found)
  89.         else if /key_table[key][itemval]
  90.  
  91.         # give it its initial value
  92.         then key_table[key][itemval] := page_num
  93.  
  94.         # otherwise just add it to the existing page number set
  95.         else key_table[key][itemval] ++:= page_num
  96.         }
  97.  
  98.     # now that all the input has been read....
  99.     # sort keys and subtables by key value
  100.     key_table := sort(key_table, 3)
  101.  
  102.     # loop, discarding the sort keys
  103.     while get(key_table) do
  104.         {
  105.         # dequeue and sort one subtable into a list
  106.         # sort is strictly by ASCII order within the equivalence class
  107.         item_list := sort(get(key_table), 3)
  108.  
  109.         # loop, consuming the item and the page number sets as we go
  110.         while one_item := get(item_list) do
  111.             {
  112.             # convert the page number set into a sorted list
  113.             page_list := sort(get(item_list))
  114.  
  115.             # dequeue first integer and convert to string
  116.             refs := string(get(page_list))
  117.  
  118.             # dequeue rest of page nums and append
  119.             while (refs ||:= ", " || string(get(page_list)))
  120.  
  121.             write("\\item ", one_item, " ", refs)
  122.             }
  123.         }
  124.     return
  125. end
  126.  
  127. # reform - modify the item to enforce sort order appropriately
  128. # This could do much more. For example it could strip leading braces,
  129. # control sequences, quotation marks, etc.  It doesn't.  Maybe later.
  130. procedure reform(item)
  131.    item := map(item)        # map to lowercase
  132. # drop leading article if present
  133.    if match("a ",   item) then return item[3:0]
  134.    if match("an ",  item) then return item[4:0]
  135.    if match("the ", item) then return item[5:0]
  136.    return item
  137. end
  138.